﻿using System;
using System.Diagnostics.Contracts;
using System.IO;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal class Feat11FieldDataItem
    {
        private Feat11FdaAutoFilter _autoFilter;
        private uint _cbFmtAgg;
        private uint _cbFmtInsertRow;
        private CachedDiskHeader _dskHdrCache;
        private DXFN12List _dxfFmtAgg;
        private DXFN12List _dxfFmtInsertRow;
        private bool _fAutoCreateCalcCol;
       // private bool _fAutoFilter;
        private bool _fAutoFilterHidden;
        private bool _fLoadFmla;
        private bool _fLoadTotalArray;
        private bool _fLoadTotalFmla;
        private bool _fLoadTotalStr;
        private bool _fLoadXmapi;
        private bool _fSaveStyleName;
        private Feat11Fmla _fmla;
        private uint _idField;
        private AggregationFunction _ilta;
        private uint _istnAgg = 0xFFFFFFFF;
        private uint _istnInsertRow = 0xFFFFFFFF;
        private uint _lfdt;
        private SOMITEM _lfxidt;
        private uint? _qsif;
        private bool _reserved2;
        private Feat11XMap _rgXmap;
        private XLUnicodeString _strCaption;
        private bool has_strCaption;
        private XLUnicodeString _strTotal;
        private Feat11TotalFmla _totalFmla;
        private bool _unused1;
        private bool _unused12;
        private ushort _unused2;
        private Feat11WSSListInfo _wssInfo;

        public Feat11FieldDataItem(TableColumn column, uint id)
        {
            this._strCaption = (XLUnicodeString) column.Name;
            this.has_strCaption = true;
            this._idField = id;
            this._autoFilter = new Feat11FdaAutoFilter();
        }

        public Feat11FieldDataItem()
        {
        }

        protected ushort GetAk (bool autoFilter)
        {
            {
                ushort result = _akRemainder;
                if (autoFilter) result |= 0x01;
                if (_fAutoFilterHidden) result |= 0x02;
                if (_fLoadXmapi) result |= 0x04;
                if (_fLoadFmla) result |= 0x08;
                if (_unused1) result |= 0x10;
                if (_unused12) result |= 0x20;
                if (_reserved2) result |= 0x40;
                if (_fLoadTotalFmla) result |= 0x80;
                if (_fLoadTotalArray) result |= 0x100;
                if (_fSaveStyleName) result |= 0x200;
                if (_fLoadTotalStr) result |= 0x400;
                if (_fAutoCreateCalcCol) result |= 0x800;
                
                return result;
            }
        }

        public XLUnicodeString _strFieldName;
        private ushort _akRemainder;

        public string Caption
        {
            get { return (string) _strCaption; }
        }

        public string StrFieldName
        {
            get { return (string) _strFieldName; }
        }


        public void Read(BinaryReader reader, SourceType lt, bool crwHeader, bool fSingleCell, SourceType sourceType)
        {
            _idField = reader.ReadUInt32();
            _lfdt = reader.ReadUInt32();
            _lfxidt = (SOMITEM)reader.ReadUInt32();
            Contract.Assert(sourceType == SourceType.LTXML || Enum.IsDefined(typeof(SOMITEM), _lfxidt));
            _ilta = (AggregationFunction) reader.ReadInt32();
            Contract.Assert(Enum.IsDefined(typeof (AggregationFunction), _ilta));
            _cbFmtAgg = reader.ReadUInt32();
            _istnAgg = reader.ReadUInt32();
            ushort ak = reader.ReadUInt16();
            var fAutoFilter = (ak & 0x01) != 0;
            _fAutoFilterHidden = (ak & 0x02) != 0;
            _fLoadXmapi = (ak & 0x04) != 0;
            _fLoadFmla = (ak & 0x08) != 0;
            _unused1 = (ak & 0x10) != 0;
            _unused12 = (ak & 0x20) != 0;
            _reserved2 = (ak & 0x40) != 0;
            _fLoadTotalFmla = (ak & 0x80) != 0;
            _fLoadTotalArray = (ak & 0x100) != 0;
            _fSaveStyleName = (ak & 0x200) != 0;
            _fLoadTotalStr = (ak & 0x400) != 0;
            _fAutoCreateCalcCol = (ak & 0x800) != 0;
            this._akRemainder = (ushort) (ak & 0xF000);
            Contract.Assert((GetAk(fAutoFilter) == ak));
            _unused2 = reader.ReadUInt16();
            _cbFmtInsertRow = reader.ReadUInt32();
            _istnInsertRow = reader.ReadUInt32();
            //\\if (lt == SourceType.LTSHAREPOINT || lt == SourceType.LTEXTERNALDATA)
            {
                _strFieldName = new XLUnicodeString();
                _strFieldName.Read(reader);
            }
            if (!fSingleCell)
            {
                _strCaption = new XLUnicodeString();
                has_strCaption = true;
                _strCaption.Read(reader);
            }
            if (_cbFmtAgg > 0)_dxfFmtAgg = new DXFN12List(reader, (int) _cbFmtAgg);
            if (_cbFmtInsertRow > 0) _dxfFmtInsertRow = new DXFN12List(reader, (int) _cbFmtInsertRow);
            if (fAutoFilter) _autoFilter = new Feat11FdaAutoFilter(reader);
            if (_fLoadXmapi) _rgXmap = new Feat11XMap(reader);
            if (_fLoadFmla) _fmla = new Feat11Fmla(reader);
            if (_fLoadTotalFmla) _totalFmla = new Feat11TotalFmla(reader);
            if (_fLoadTotalStr)
            {
                _strTotal = new XLUnicodeString();
                _strTotal.Read(reader);
            }
            if (lt == SourceType.LTSHAREPOINT) _wssInfo = new Feat11WSSListInfo(reader);
            if (lt == SourceType.LTEXTERNALDATA) _qsif = reader.ReadUInt32();
            if (crwHeader == false && fSingleCell == false) _dskHdrCache = new CachedDiskHeader(reader);
        }

        public void Write(BinaryWriter writer)
        {
            writer.Write(_idField);
            writer.Write(_lfdt);
            writer.Write((uint)_lfxidt  );
            writer.Write((int)_ilta);
            writer.Write(_cbFmtAgg );
            writer.Write(_istnAgg );
            writer.Write(GetAk(this._autoFilter != null));
            writer.Write(_unused2 );
            writer.Write(_cbFmtInsertRow  );
            writer.Write(_istnInsertRow  );
            //\\if (lt == SourceType.LTSHAREPOINT || lt == SourceType.LTEXTERNALDATA)
            {
                _strFieldName.Write(writer);
            }
            if (has_strCaption)
            {
               _strCaption.Write(writer);
            }
            if (_cbFmtAgg > 0)
            {
                _dxfFmtAgg.Write(writer);
            }
            if (_cbFmtInsertRow > 0) _dxfFmtInsertRow.Write(writer);
            if (_autoFilter != null) _autoFilter.Write(writer);
            if (_fLoadXmapi) _rgXmap.Write(writer);
            if (_fLoadFmla) _fmla.Write(writer);
            if (_fLoadTotalFmla) _totalFmla.Write(writer);
            if (_fLoadTotalStr)
            {
                _strTotal.Write(writer);
            }
            if (_wssInfo != null) _wssInfo.Write(writer);
            if (_qsif != null)writer.Write(_qsif.Value);
            if (_dskHdrCache != null) _dskHdrCache.Write(writer);
        }
    }
}